package com.cw.lang.validator.constraintvalidators;

import java.util.ArrayList;
import java.util.List;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.springframework.cglib.core.ReflectUtils;
import org.springframework.util.StringUtils;

import com.cw.lang.validator.constants.ValidatorConstants;
import com.cw.lang.validator.constraints.CheckWith;
import com.cw.lang.validator.constraints.Validator;

/**
 * @author chenw
 * @version $$Id: CheckWithValidator.java, v 0.1 2018/9/20 下午1:38 chenw Exp $$
 */
public class CheckWithValidator implements ConstraintValidator<CheckWith, Object> {

    private List<SimpleCheckWrapper> simpleCheckWrapperList = new ArrayList<>();

    @Override
    public void initialize(CheckWith constraintAnnotation) {
        Class<? extends SimpleCheck> simpleCheckClazz = constraintAnnotation.value();
        simpleCheckWrapperList.add(SimpleCheckWrapper.builder().simpleCheck(newInstance(simpleCheckClazz))
            .message(constraintAnnotation.message()).build());
        if (constraintAnnotation.checker().length > 0) {
            for (Validator validator : constraintAnnotation.checker()) {
                simpleCheckWrapperList.add(SimpleCheckWrapper.builder().simpleCheck(newInstance(validator.value()))
                    .message(StringUtils.isEmpty(constraintAnnotation.message()) ? ValidatorConstants.CHECK_WITH_DEFAULT_MESSAGE :
                        constraintAnnotation.message()).build());
            }
        }
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        for (SimpleCheckWrapper simpleCheckWrapper : simpleCheckWrapperList) {
            boolean result = simpleCheckWrapper.getSimpleCheck().isSatisfied(value);
            if (!result) {
                //禁用默认的message的值
                context.disableDefaultConstraintViolation();
                //重新添加错误提示语句
                context.buildConstraintViolationWithTemplate(simpleCheckWrapper.getMessage()).addConstraintViolation();
                return false;
            }
        }
        return true;
    }

    /**
     * 实例化校验器
     *
     * @param clazz 校验器
     * @return 实例化后的校验器
     */
    private SimpleCheck newInstance(Class<? extends SimpleCheck> clazz) {
        return (SimpleCheck) ReflectUtils.newInstance(clazz);
    }
}
